use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize};
use std::{collections::HashSet, fmt};
use utoipa::ToSchema;

/// ID请求
#[derive(Debug, Deserialize, Serialize, ToSchema)]
pub struct IdRequest {
    /// ID
    pub id: i32,
}

/// ID请求
#[derive(Debug, Serialize, ToSchema)]
pub struct IdsRequest {
    /// ID
    pub ids: Vec<i32>,
}

/// 点查请求
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct PointRequest {
    pub point: String,
}

impl<'de> Deserialize<'de> for IdsRequest {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct IdsVisitor;

        impl<'de> Visitor<'de> for IdsVisitor {
            type Value = IdsRequest;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                let json_error =
                    r#"{"error": "expected a comma-separated string or a sequence of integers"}"#;
                formatter.write_str(json_error)
            }

            // 处理查询参数映射
            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
            where
                M: de::MapAccess<'de>,
            {
                let mut ids = HashSet::new();
                while let Some((key, value)) = map.next_entry::<String, String>()? {
                    if key == "ids" {
                        ids = value
                            .split(',')
                            .filter_map(|s| {
                                let s = s.trim();
                                if s.is_empty() {
                                    None
                                } else {
                                    s.parse::<i32>().ok()
                                }
                            })
                            .collect();
                    }
                }
                Ok(IdsRequest {
                    ids: ids.into_iter().collect(),
                })
            }
        }

        // 允许反序列化为任意类型（字符串或序列）
        deserializer.deserialize_any(IdsVisitor)
    }
}
